package utils

import (
	"bytes"
	"fmt"
	"hft/Database/admin"
	"hft/Http/Models/response"
	"hft/global"
	"hft/tools/phone/api"
	"hft/tools/phone/model"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"time"

	"golang.org/x/net/html"
	"gorm.io/gorm"
)

// 构建多叉树路由

func BuildRoutesTree(routes []*admin.Route, pid uint) []*admin.Route {
	var newRoutes []*admin.Route
	for _, v := range routes {
		if v.PID == pid {
			v.Children = BuildRoutesTree(routes, v.ID)
			newRoutes = append(newRoutes, v)
		}
	}
	return newRoutes
}

// 全查后递归
func BuildTree(nodes []*admin.Role, rootId uint) *admin.Role {
	var root *admin.Role
	for _, node := range nodes {
		if node.ID == rootId {
			root = node
		}
		for _, child := range nodes {
			if child.PID == node.ID {
				node.Roles = append(node.Roles, child)
			}
		}
	}
	return root
}

// 设置分销链

func SetLink(root *admin.Region, node *admin.Region) {
	if node.PID != 0 {
		node.Link = fmt.Sprintf("%v%v,", root.Link, node.PID)
	} else {
		node.Link = ","
	}
	if len(node.Districts) != 0 {
		for _, child := range node.Districts {
			SetLink(node, child)
		}
	}
}

// 扁平化数组

func FlattenRegion(region *admin.Region) []*admin.Region {
	flattened := []*admin.Region{region}
	for _, district := range region.Districts {
		flattened = append(flattened, FlattenRegion(district)...)
	}
	return flattened
}

// 根据查找的角色找出他所有的从角色
func FindSubtreeIds(roles []*admin.Role, rootId uint) []uint {
	var ids []uint
	// 遍历结构体数组中的每一个结构体
	for _, role := range roles {
		// 如果当前节点的父节点ID等于根节点ID，则将当前节点的ID添加到结果列表中
		if role.PID == rootId {
			ids = append(ids, role.ID)
			// 递归查找当前节点的子节点
			ids = append(ids, FindSubtreeIds(roles, role.ID)...)
		}
	}
	return ids
}

// 查找出地区以及所属地区
func FindSubRegions(regions []*admin.Region) []uint {
	var ids []uint
	for _, child := range regions {
		ids = append(ids, child.ID)
	}
	return ids
}

// 去除不属于改id的区域数组
func FilterRegions(regions []*admin.Region, ids []uint) []*admin.Region {
	var filteredRegions []*admin.Region
	for _, region := range regions {
		for _, id := range ids {
			if region.ID == id {
				filteredRegions = append(filteredRegions, region)
				break
			}
		}
	}
	return filteredRegions
}

// 去除没有region的属性
func FilterNoRegionAccount(account []*admin.Account) []*admin.Account {
	var arr []*admin.Account
	for _, v := range account {
		if len(v.Regions) != 0 {
			arr = append(arr, v)
		}
	}
	return arr
}

func BuildRegionForestV2(regions []*response.AccountArea) []*response.AccountArea {
	sort.Slice(regions, func(i, j int) bool {
		return regions[i].ID < regions[j].ID
	})
	regionMap := make(map[uint]*response.AccountArea)
	var roots []*response.AccountArea

	// 将所有的Region元素添加到map中
	for _, region := range regions {
		regionMap[region.ID] = region
	}

	// 将每个节点添加到父节点的districts切片中
	for _, region := range regionMap {
		parent, ok := regionMap[region.PID]
		if ok {
			// 如果父节点存在，则将当前节点添加到父节点的districts切片中
			parent.Districts = append(parent.Districts, region)
			sort.Slice(parent.Districts, func(i, j int) bool {
				return parent.Districts[i].ID < parent.Districts[j].ID
			})
		} else {
			// 否则将当前节点添加到roots切片中
			roots = append(roots, region)
			sort.Slice(roots, func(i, j int) bool {
				return roots[i].ID < roots[j].ID
			})
		}
	}

	return roots
}

// 构建地区的森林
func BuildRegionForest(regions []*admin.Region) []*admin.Region {
	sort.Slice(regions, func(i, j int) bool {
		return regions[i].ID < regions[j].ID
	})
	regionMap := make(map[uint]*admin.Region)
	var roots []*admin.Region

	// 将所有的Region元素添加到map中
	for _, region := range regions {
		regionMap[region.ID] = region
	}

	// 将每个节点添加到父节点的districts切片中
	for _, region := range regionMap {
		parent, ok := regionMap[region.PID]
		if ok {
			// 如果父节点存在，则将当前节点添加到父节点的districts切片中
			parent.Districts = append(parent.Districts, region)
			sort.Slice(parent.Districts, func(i, j int) bool {
				return parent.Districts[i].ID < parent.Districts[j].ID
			})
		} else {
			// 否则将当前节点添加到roots切片中
			roots = append(roots, region)
			sort.Slice(roots, func(i, j int) bool {
				return roots[i].ID < roots[j].ID
			})
		}
	}

	return roots
}

// 判断设置的地区是否在账号可以支配的地区内
func ContainsRegion(arr []*admin.Region, target uint) bool {
	for _, n := range arr {
		if n.ID == target {
			return true
		}
	}
	return false
}

// 判断要添加的地区是否都在同一个区域内
func AllEqual(regions []*admin.Region) bool {
	if len(regions) == 0 {
		return true
	}
	firstNum := regions[0].PID
	for _, v := range regions {
		if v.PID != firstNum {
			return false
		}
	}
	return true
}

// 判断要添加的地区是否和当前账号可以配置的地区一致
func AllSameRegion(regions []*admin.Region, regionType string) bool {
	if len(regions) == 0 {
		return true
	}
	for _, v := range regions {
		if regionType != v.Level {
			return false
		}
	}
	return true
}

// uint去重
func UniqueUintSlice(s []uint) []uint {
	m := make(map[uint]bool)
	var result []uint
	for _, v := range s {
		if _, ok := m[v]; !ok {
			m[v] = true
			result = append(result, v)
		}
	}
	return result
}

// 构建文件夹树
// 构建地区的森林
func BuildDirForest(dirs []*admin.FileGroup) []*admin.FileGroup {

	sort.Slice(dirs, func(i, j int) bool {
		return dirs[i].ID < dirs[j].ID
	})
	dirsMap := make(map[uint]*admin.FileGroup)
	var roots []*admin.FileGroup

	// 将所有的Region元素添加到map中
	for _, dir := range dirs {
		dirsMap[dir.ID] = dir
	}

	// 将每个节点添加到父节点的districts切片中
	for _, dir := range dirsMap {
		parent, ok := dirsMap[uint(dir.PID)]
		if ok {
			// 如果父节点存在，则将当前节点添加到父节点的districts切片中
			parent.Directory = append(parent.Directory, dir)
			sort.Slice(parent.Directory, func(i, j int) bool {
				return parent.Directory[i].ID < parent.Directory[j].ID
			})
		} else {
			// 否则将当前节点添加到roots切片中
			roots = append(roots, dir)
			sort.Slice(roots, func(i, j int) bool {
				return roots[i].ID < roots[j].ID
			})
		}
	}

	return roots
}

func ContainsInt(slice []int, num int) bool {
	for _, value := range slice {
		if value == num {
			return true
		}
	}
	return false
}

// 获取管辖城市
func ManageCity(str string) []int {
	var regionLink = strings.Split(str, "|")
	var regionId []int
	for _, v := range regionLink {
		var strArr = strings.Split(v, ",")
		var id, _ = strconv.Atoi(strArr[len(strArr)-2])
		regionId = append(regionId, id)
	}
	return regionId
}

// 获取用户所属管理哪些城市
func BeLongCity(str string) []int {
	var strArr = strings.Split(str, "|")
	var ids []int
	for _, v := range strArr {
		var str = strings.Split(v, ",")
		var id, _ = strconv.Atoi(str[len(str)-2])
		ids = append(ids, id)
	}
	return ids
}

func BelongMyCity(str string) []int {
	var strArr = strings.Split(str, "|")
	var ids []int
	for _, v := range strArr {
		var str = strings.Split(v, ",")
		var id, _ = strconv.Atoi(str[3])
		ids = append(ids, id)
	}
	return ids
}

func IsAllCity(regions []*admin.Region) bool {
	for _, v := range regions {
		if v.Level != "city" {
			return false
		}
	}
	return true
}

// 判断是否属于该账号
func IsBelongThisAccount(accounts []*admin.Account, manager *admin.Account) bool {

	var reg = fmt.Sprintf("^%v%v,", manager.AccountLink, manager.ID)

	for _, v := range accounts {
		match, _ := regexp.MatchString(reg, v.AccountLink)

		if !match {
			return false
		}
	}
	return true
}

// 判断是否属于该文件夹
func IsBelongThisFileGroup(files []*admin.FileUploadAndDownload, link string) bool {

	for _, v := range files {

		fmt.Println(fmt.Sprintf("^%v", link), v.Link)

		match, _ := regexp.MatchString(fmt.Sprintf("^%v", link), v.Link)

		if !match {
			return false
		}
	}
	return true
}

func IsBelongThisRegion(regions []*admin.Region, link string) bool {
	for _, v := range regions {
		match, _ := regexp.MatchString(fmt.Sprintf("(%v)", link), v.Link)

		if !match {
			return false
		}
	}
	return true
}

// 判断轮播图是否属于该地区

func IsSwiperBelongThisRegion(swiper []*admin.HomeSwiper, link string) bool {
	for _, v := range swiper {
		match, _ := regexp.MatchString(fmt.Sprintf("^(%v)", link), v.RegionLink)

		if !match {
			return false
		}
	}
	return true
}

// 要删除的友情链接是否都属于该地区
func IsAllLinksBelongThisRegion(links []*admin.FriendlyLink, link string) bool {

	for _, v := range links {
		match, _ := regexp.MatchString(fmt.Sprintf("^(%v)", link), v.RegionLink)

		if !match {
			return false
		}
	}
	return true

}

func Audit(isNeed bool) (num int) {
	if isNeed {
		return 1
	} else {
		return 2
	}
}

// 获取账号所属
func AccountBelongRegion(regionLink string, db *gorm.DB) (belongName string) {

	strArr := strings.Split(regionLink, ",")

	strArr = strArr[2 : len(strArr)-1]

	var regionList []int

	for _, v := range strArr {

		var id, _ = strconv.Atoi(v)

		regionList = append(regionList, id)
	}

	var regionNameArr []string

	var regions []*admin.Region

	db.Find(&regions, regionList)

	for _, v := range regions {
		regionNameArr = append(regionNameArr, v.Name)
	}

	str := strings.Join(regionNameArr, "-")

	return str

}

// 去掉字符串空格

func DeleteStringSpace(name string) string {

	if name == "" {
		return name
	} else {
		return regexp.MustCompile(`\s+`).ReplaceAllString(name, "")
	}

}

// 判断楼盘是否都属于账号的关系范围
func IsThisLouBelongThisAccount(list []*admin.LouPan, regionLink string) bool {
	for _, v := range list {

		match, _ := regexp.MatchString(fmt.Sprintf("^%v", regionLink), v.RegionLink)

		if !match {
			return false
		}

	}

	return true
}

// 判断文章是否属于该城市
func IsThisArtBelongThisAccount(list []*admin.ArticleBase, regionLink string) bool {

	for _, v := range list {

		match, _ := regexp.MatchString(fmt.Sprintf("^%v", regionLink), v.RegionLink)

		if !match {
			return false
		}

	}

	return true

}

// 判断动态是否属于账号
func IsThisActBelongThisAccount(list []*admin.ActiveBase, accountLink string) bool {

	for _, v := range list {

		match, _ := regexp.MatchString(fmt.Sprintf("^%v", accountLink), v.AccountLink)

		if !match {
			return false
		}

	}
	return true
}

// 判断排行标签是否属于该账号
func IsThisDisBelongThisAccount(list []*admin.Disadvantage, regionLink string) bool {

	for _, v := range list {

		match, _ := regexp.MatchString(fmt.Sprintf("^%v", regionLink), v.RegionLink)

		if !match {
			return false
		}

	}

	return true
}

// 获取区域所属城市
func GetRegionBelongCity(regionLink string) (city int, cityLink string) {
	var strArr = strings.Split(regionLink, ",")

	strArr = strArr[1 : len(strArr)-1]

	cityId, _ := strconv.Atoi(strArr[2])

	if len(strArr) == 3 {
		return cityId, "," + strings.Join(strArr, ",") + ","
	} else {
		return cityId, "," + strings.Join(strArr[:len(strArr)-1], ",") + ","
	}

}

// 判断两个时间是否超过24小时
func IsTimeDifferenceGreaterThan24Hours(t1, t2 time.Time) bool {
	diff := t1.Sub(t2)
	hours := diff.Hours()
	return hours > 24 || hours < -24
}

// 地区所属BelongName
func RegionBelong(regionLink string, db *gorm.DB) string {

	var strArr = strings.Split(regionLink, ",")

	if len(strArr) < 3 {
		return ""
	}
	strArr = strArr[2 : len(strArr)-1]

	var ids []int

	for _, v := range strArr {

		var id, _ = strconv.Atoi(v)

		ids = append(ids, id)
	}

	var regions []*admin.Region

	global.OC_DB.Find(&regions, ids)

	var link string

	for _, v := range regions {
		link = link + v.Name + "-"
	}

	return link[:len(link)-1]
}

// 手机脱敏
func DesensitizePhoneNumber(phoneNumber string) string {
	// 去除非数字字符
	reg := regexp.MustCompile(`\D`)
	processedNumber := reg.ReplaceAllString(phoneNumber, "")

	// 脱敏处理
	//大陆手机
	if len(phoneNumber) == 11 {
		return processedNumber[:3] + "****" + processedNumber[7:len(phoneNumber)]
	} else {
		// 香港澳门
		return processedNumber[:2] + "****" + processedNumber[6:len(phoneNumber)]
	}

}

func GetIns(str string) []int {
	str = DeleteStringSpace(str)

	var ids []int

	if str == "" {
		return ids
	}

	strArr := strings.Split(str, ",")

	for _, v := range strArr {
		var id, _ = strconv.Atoi(v)
		ids = append(ids, id)
	}

	return ids
}

// 获取开盘时间
func GetOpenTime(roomType int) int64 {

	currentTime := time.Now()

	year, month, _ := currentTime.Date()

	firstDayOfMonth := time.Date(year, month, 1, 0, 0, 0, 0, currentTime.Location())
	firstDayOfNextMonth := firstDayOfMonth.AddDate(0, 1, 0)

	if roomType == 1 {
		return firstDayOfNextMonth.Add(-time.Second).UnixMilli()
	} else if roomType == 2 {
		return MonthTime(firstDayOfMonth, 1)
	} else if roomType == 3 {
		return MonthTime(firstDayOfMonth, 3)
	} else if roomType == 4 {
		return MonthTime(firstDayOfMonth, 6)
	} else if roomType == 5 {
		return MonthTime(firstDayOfMonth, -1)
	} else if roomType == 6 {
		return MonthTime(firstDayOfMonth, -6)
	} else {
		return 0
	}
}

// 未来或者过去几个月
func MonthTime(monthTime time.Time, month int) int64 {
	return monthTime.AddDate(0, month, -1).UnixMilli()
}

// 获取分机号
func GetDns(list []*admin.LouPan, phone string, db *gorm.DB) string {

	// 批量查出分机号

	var dns []string

	for _, v := range list {

		if v.SellLouPanInfo.SellPhone != "" {
			dns = append(dns, v.SellLouPanInfo.SellPhone)
		}

	}

	var dnsList []*admin.DNBroker

	if len(dns) == 0 {
		return "0"
	}

	db.Where("dn IN ?", dns).Find(&dnsList)

	var newlist []*model.Row
	for _, v := range dnsList {
		if v.Tel == "" {
			v.Tel = phone
		} else {
			v.Tel = strings.Join(UniqueSlice(append(strings.Split(v.Tel, "|"), phone)), "|")
		}
		db.Model(&admin.DNBroker{}).Where("dn = ?", v.Dn).Update("tel", v.Tel)

		var row = &model.Row{Dn: v.Dn, Tel: v.Tel, TransType: "rnd"}
		newlist = append(newlist, row)
	}

	code := api.PhoneVirtual.AddOrEditPhone(newlist)

	return code

}

// 字符串切片去重
func UniqueSlice(slice []string) []string {
	// 创建一个空的map，用于记录出现过的字符串
	seen := make(map[string]struct{})
	unique := make([]string, 0)

	// 遍历切片中的每个元素
	for _, str := range slice {
		// 检查字符串是否已经在map中存在
		if _, ok := seen[str]; !ok {
			// 如果字符串不存在，则将其添加到map和结果切片中
			seen[str] = struct{}{}
			unique = append(unique, str)
		}
	}

	return unique
}

// 去掉手机
func DeletePhone(list []*admin.LouPan, phone string, accountPhone string, db *gorm.DB) (code string) {
	var dnsList []*admin.DNBroker
	var dns []string
	var rows []*model.Row
	for _, v := range list {
		if v.SellLouPanInfo.SellPhone != "" {
			dns = append(dns, v.SellLouPanInfo.SellPhone)
		}
	}

	if len(dns) == 0 {
		return "0"
	}

	db.Where("dn IN ?", dns).Find(&dnsList)

	// 去掉楼盘里的电话
	for _, v := range dnsList {
		var strs = strings.Split(v.Tel, "|")
		strs = FilterSlice(phone, strs)
		if len(strs) == 0 {
			v.Tel = ""
		} else {
			v.Tel = strings.Join(strs, "|")
		}
		db.Model(&admin.DNBroker{}).Where("dn = ?", v.Dn).Update("Tel", v.Tel)
		if v.Tel == "" {
			var dn = &model.Row{Dn: v.Dn, Tel: accountPhone, TransType: "rnd"}
			rows = append(rows, dn)
		} else {
			var dn = &model.Row{Dn: v.Dn, Tel: v.Tel, TransType: "rnd"}
			rows = append(rows, dn)
		}

	}

	code = api.PhoneVirtual.AddOrEditPhone(rows)

	return code
}

// 去掉字符串切片中的某个字符串
func FilterSlice(str string, slice []string) []string {
	filtered := make([]string, 0)

	// 遍历切片中的每个元素
	for _, item := range slice {
		// 如果元素不等于输入的字符串，则将其添加到新的切片中
		if item != str {
			filtered = append(filtered, item)
		}
	}

	return filtered
}

// 提取纯文本
func ConvertHTMLToPlainText(htmlString string) (plainText string, err error) {
	// 解析HTML字符串
	doc, err := html.Parse(strings.NewReader(htmlString))
	if err != nil {
		return "", err
	}

	// 遍历解析后的HTML节点，提取纯文本内容
	var buf bytes.Buffer
	var visitNode func(node *html.Node)
	visitNode = func(node *html.Node) {
		if node.Type == html.TextNode {
			buf.WriteString(node.Data) // 提取文本内容
		}

		for child := node.FirstChild; child != nil; child = child.NextSibling {
			visitNode(child) // 递归遍历子节点
		}
	}
	visitNode(doc)

	return buf.String(), nil
}

// 选择保护天数
func ChooseProtectDay(level string, citySet *admin.CitySetting) float32 {
	switch level {
	case "A":
		return citySet.LevelA
	case "B":
		return citySet.LevelB
	case "C":
		return citySet.LevelC
	case "D":
		return citySet.LevelD
	// case "E":
	// 	return citySet.LevelE
	// case "F":
	// 	return citySet.LevelF
	default:
		return 0
	}
}

// int类型去重
func DeduplicateIntSlice(slice []int) []int {
	seen := make(map[int]bool)
	result := []int{}

	for _, val := range slice {
		if !seen[val] {
			seen[val] = true
			result = append(result, val)
		}
	}

	return result
}

// 判断ids是否一致
func JudgeIDSSame(ids []int) bool {
	if len(ids) < 2 {
		return true
	}
	firstElement := ids[0]
	for _, v := range ids {
		if v != firstElement {
			return false
		}
	}
	return true
}
